home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 January: Mac OS SDK / Dev.CD Jan 96 SDK / Dev.CD Jan 96 SDK1.toast / Development Kits (Disc 1) / AppleScript / Development Tools / Sample Code / 7Edit / Pascal Sources / SVEditions.p < prev    next >
Encoding:
Text File  |  1994-02-25  |  46.5 KB  |  1,598 lines  |  [TEXT/MPS ]

  1.  
  2. {[d-,h-,k+,o=100,q+,r+,rec+,t=2,u+,:+,j=15/20/25/30/35/40/45/50/57/1$]} {Pasmat opts!}
  3.  
  4. UNIT SVEditions;
  5.  
  6. {
  7.     SVEditions.p
  8.     
  9.     Version 3.0d8
  10.     
  11.     Copyright © SRL Data 1992, 1993
  12.     
  13.     All rights reserved
  14.     
  15.     Produced by : SRL Data
  16.     Originally Developed for UK.DTS
  17.  
  18.     The Edition Manager routines from the 7Edit example.
  19.  
  20. Known incomplete bits-:
  21.     i)         Handling the mouse downs for Publishers and Subscribers is not all there-
  22.                 future versions will include double clicking to open the section options dialog,
  23.                 for example.
  24.     ii)     There are problems if an edition is moved from the Finder- there needs to
  25.                 be code added to handle orphaned sections.
  26.     iii)     We need to issue a warning if a document is disposed of containing
  27.                 sections that will be lost.
  28. }
  29.  
  30. {
  31.     Changes for 3.0d2 :
  32.         10-Feb-92    : NH    :    Tidy up dead vars etc.
  33.         11-Feb-92    :    NH    : Fix bug in read of saved document with sections - ReadSectionRecords
  34.         20-Feb-92 : NH  : Put in new code to handle section position changes due to paste, key etc.
  35.                                                 DoTEPasteSectionRecalc,
  36.                                                 DoTEDeleteSectionRecalc,
  37.                                                 DoTECutSectionRecalc,
  38.                                                 DoTEKeySectionRecalc,        
  39.                                                 KeyOKinSubscriber,
  40.                                                 DoSectionRecalc
  41.         22-Feb-92: NH        : Code the 'styl' part of editions.
  42.         25-Feb-92: NH        : Fix publisher borders clipping.
  43.         26-Feb-92: NH        : Draw Borders to edge of printed page not window.
  44.         27-Feb-92: NH        : gCurrSection zapped.
  45.         28-Feb-92: NH        : PublishText via AppleEvent
  46.         18-Mar-92: NH        : Old comments updates/zapped
  47.         19-Mar-92: NH        : Fix Edition code so finder can open publisher etc.
  48.     
  49.     Changes for 3.0d4 :
  50.          9-Jul-92: NH   : AEInteractWithUser before NewPublisherDialog
  51.  
  52. }
  53.  
  54.     INTERFACE
  55.  
  56.         USES MemTypes, QuickDraw, OSIntf, ToolIntf, Traps, Menus, Packages, PPCToolbox, Editions, Printing,
  57.                  SVEditGlobals, SVEditUtils;
  58.  
  59.         PROCEDURE AddSection(newSection: SectHandle;
  60.                                                  aDocument: DPtr);
  61.  
  62.         PROCEDURE CreateSection(EMSection    : SectionHandle;
  63.                                                         sectionID    : INTEGER;
  64.                                                         theStart     : INTEGER;
  65.                                                         theEnd        : INTEGER;
  66.                                                         aDocument    : DPtr;
  67.                                                         theBorder    : RgnHandle);
  68.  
  69.         PROCEDURE DeleteASection(sectToDelete: SectHandle;
  70.                                                          theDoc: DPtr);
  71.  
  72.         PROCEDURE AssocAllSections(theDoc: DPtr);
  73.  
  74.         {routines for writing out and reading in section resources}
  75.         {rAliasType and rSectionType resources}
  76.  
  77.         PROCEDURE ReadAllSectionResources(aDoc: DPtr);
  78.  
  79.         PROCEDURE ReadSectionRecords(aDoc: DPtr);
  80.  
  81.         PROCEDURE ReadASection(aSectHandle: SectHandle);
  82.  
  83.         PROCEDURE SaveASection(aSection: SectHandle;
  84.                                                      count: INTEGER);
  85.  
  86.         PROCEDURE SaveSections(aDocument: DPtr);
  87.  
  88.         {routines for writing out editions}
  89.  
  90.         PROCEDURE ReadAnEdition(mySectHdl: SectionHandle);
  91.  
  92.         PROCEDURE WriteAllEditions(aDocument: DPtr);
  93.  
  94.         PROCEDURE WriteAnEdition(mySectHdl: SectionHandle);
  95.  
  96.         {routines for handling the section borders}
  97.  
  98.         FUNCTION GetSection(theStartPos, theEndPos: INTEGER;
  99.                                                 aDoc: DPtr): SectHandle;
  100.  
  101.         PROCEDURE RecalcBorders(aDoc: DPtr;
  102.                                                         invalidate: BOOLEAN);
  103.  
  104.         PROCEDURE SetSelectionRgn(theTEHandle: TEHandle;
  105.                                                             posStart, posEnd: INTEGER;
  106.                                                             VAR theSelRgn: RgnHandle);
  107.  
  108.         PROCEDURE ShowSectionBorders(aDoc: DPtr);
  109.         
  110.         PROCEDURE DoTEPasteSectionRecalc(theDoc : DPtr);
  111.         
  112.         PROCEDURE DoTEDeleteSectionRecalc(theDoc : DPtr);
  113.         
  114.         PROCEDURE DoTECutSectionRecalc(theDoc : DPtr);
  115.  
  116.         PROCEDURE DoTEKeySectionRecalc(theDoc : DPtr; theChar:CHAR);
  117.         
  118.         {utility routines}
  119.  
  120.         FUNCTION GetERefCon(EMSection: SectionHandle): SectHandle;
  121.  
  122.         PROCEDURE SetERefCon(EMSection: SectionHandle;
  123.                                                  aSectHandle: SectHandle);
  124.  
  125.         PROCEDURE DeRegisterAllSections(aDoc: DPtr);
  126.  
  127.         FUNCTION GetHandleToText(aTEHandle: TEHandle;
  128.                                                          theStart, theEnd: INTEGER): Handle;
  129.  
  130.         {now the routines for dealing with the user interface issues}
  131.  
  132.         PROCEDURE DoSectionOptions(theDoc: DPtr);
  133.  
  134.         PROCEDURE DoSubscribe(theDoc: DPtr);
  135.  
  136.         FUNCTION GetEditionContainer(theDoc: DPtr; VAR theFSSpec:FSSpec): OSErr;
  137.  
  138.         FUNCTION PublishText(theDoc: DPtr; theFSSpec:FSSpecPtr): OSErr;
  139.         
  140.         FUNCTION  KeyOKinSubscriber(whatKey:Char):BOOLEAN;
  141.  
  142.     IMPLEMENTATION
  143.     
  144.         USES AppleEvents;
  145.         
  146. {*-----------------------------------------------------------------------
  147.         Name:             GetERefCon
  148.         Purpose:        Return the sectHandle (our own type) stored in
  149.                                 the refcon of the SectionRecord.
  150.     -----------------------------------------------------------------------*}
  151.  
  152.         {$S Editions}
  153.  
  154.         FUNCTION GetERefCon(EMSection: SectionHandle): SectHandle;
  155.  
  156.             VAR
  157.                 aSectHandle     : SectHandle;
  158.  
  159.             BEGIN
  160.                 {returns the current refcon for this section as a SectHandle}
  161.                 aSectHandle := SectHandle(EMSection^^.refCon);
  162.                 GetERefCon := aSectHandle;
  163.             END;
  164.  
  165.     {*-----------------------------------------------------------------------
  166.         Name:             SetERefCon
  167.         Purpose:        Store a handle to our own SectRecord in the refcon
  168.                                 field of the SectionRecord.
  169.     -----------------------------------------------------------------------*}
  170.  
  171.         {$S Editions}
  172.  
  173.         PROCEDURE SetERefCon(EMSection: SectionHandle;
  174.                                                  aSectHandle: SectHandle);
  175.  
  176.             BEGIN
  177.                 {set up the refcon for the given section}
  178.                 EMSection^^.refCon := ORD4(aSectHandle);
  179.             END;
  180.  
  181. {*-----------------------------------------------------------------------
  182.         Name:             AddSection
  183.         Purpose:        Add our own section record to the document linked
  184.                                 list.  Set up the first and last section variables.
  185.     -----------------------------------------------------------------------*}
  186.  
  187.         {$S Editions}
  188.  
  189.         PROCEDURE AddSection(newSection: SectHandle;
  190.                                                  aDocument: DPtr);
  191.  
  192.  
  193.             BEGIN
  194.                 (*
  195.                     add the section to the document
  196.                 *)
  197.                 aDocument^.numSections := aDocument^.numSections + 1;
  198.  
  199.                 (*
  200.                     if not NIL, add the new section to the list after the last element
  201.                 *)
  202.                 IF (aDocument^.lastSection <> NIL) THEN
  203.                     aDocument^.lastSection^^.fNextSection := newSection
  204.                 ELSE
  205.                     aDocument^.firstSection := newSection;
  206.                 
  207.                 aDocument^.lastSection     := newSection;
  208.                 newSection^^.fNextSection  := NIL;
  209.             END;
  210.  
  211. {*-----------------------------------------------------------------------
  212.         Name:             CreateSection
  213.         Purpose:        Create a new section record to hold a Publisher or
  214.                                 Subscriber. Link this to the SectionRecord.
  215.     -----------------------------------------------------------------------*}
  216.  
  217.         {$S Editions}
  218.  
  219.         PROCEDURE CreateSection(EMSection    : SectionHandle;
  220.                                                         sectionID    : INTEGER;
  221.                                                         theStart     : INTEGER;
  222.                                                         theEnd        : INTEGER;
  223.                                                         aDocument    : DPtr;
  224.                                                         theBorder    : RgnHandle);
  225.  
  226.             VAR
  227.                 newSection        : SectHandle;
  228.  
  229.             BEGIN
  230.                 (*
  231.                     create a section and call AddSection to add it to the list
  232.                 *)
  233.                 newSection := SectHandle(NewHandle(SizeOf(sectRec)));
  234.                 
  235.                 IF (newSection<>NIL) THEN
  236.                     BEGIN
  237.                         newSection^^.fSectionID   := sectionID;
  238.                         newSection^^.fNextSection := NIL;
  239.                         newSection^^.fSectHandle  := EMSection;
  240.                         newSection^^.fStart       := theStart;
  241.                         newSection^^.fEnd         := theEnd;
  242.                         newSection^^.fCount       := theEnd - theStart;
  243.                         newSection^^.fBorderRgn   := theBorder;
  244.                         newSection^^.fDocument    := aDocument;
  245.         
  246.                         (*
  247.                             put a reference to our section record in the section's refCon field
  248.                         *)
  249.                         SetERefCon(EMSection, newSection);
  250.                         AddSection(newSection, aDocument);
  251.                     END;
  252.             END;
  253.  
  254.  {*-----------------------------------------------------------------------
  255.         Name:             DeleteASection
  256.         Purpose:        Delete the section from the list.
  257.                                 Called when 'Cancel Publisher/Subscriber is chosen in
  258.                                 the 'Section Options' dialog.
  259.     -----------------------------------------------------------------------*}
  260.  
  261.         {$S Editions}
  262.  
  263.         PROCEDURE DeleteASection(sectToDelete: SectHandle;
  264.                                                          theDoc: DPtr);
  265.  
  266.             VAR
  267.                 currSect     : SectHandle;
  268.                 prevSect    : SectHandle;
  269.  
  270.             BEGIN
  271.                 currSect := theDoc^.firstSection;
  272.                 prevSect := NIL;
  273.  
  274.                 WHILE currSect <> NIL DO
  275.                     BEGIN
  276.                         IF (currSect = sectToDelete) THEN
  277.                             BEGIN
  278.                                 (*
  279.                                     unlink the section from the list
  280.                                 *)
  281.                                 IF (prevSect <> NIL) THEN
  282.                                     prevSect^^.fNextSection := currSect^^.fNextSection;
  283.                                 IF (currSect = theDoc^.firstSection) THEN
  284.                                     theDoc^.firstSection := NIL;
  285.                                 IF (currSect = theDoc^.lastSection) THEN
  286.                                     theDoc^.lastSection := NIL;
  287.                             END;
  288.                         prevSect := currSect;
  289.                         currSect := currSect^^.fNextSection;
  290.                     END;
  291.             END;
  292.  
  293. {*-----------------------------------------------------------------------
  294.         Name:             ReadASection
  295.         Purpose:        Read in a section from disk
  296.                                 Read in the rAliasType and rsectionType resources and register
  297.                                 the section with the document.
  298.     -----------------------------------------------------------------------*}
  299.  
  300.         {$S Editions}
  301.  
  302.         PROCEDURE ReadASection(aSectHandle: SectHandle);
  303.  
  304.             VAR
  305.                 aSectionHandle: SectionHandle;
  306.                 anAlias             : AliasHandle;
  307.                 err                     : OSErr;
  308.                 myFSSpec            : FSSpec;
  309.                 ignore                : BOOLEAN;
  310.  
  311.             BEGIN
  312.                 {read in the rAliasType and rSectionType resources}
  313.                 
  314.                 aSectionHandle := SectionHandle(Get1Resource(rSectionType, aSectHandle^^.fSectionID));
  315.                 err            := HandtoHand(Handle(aSectionHandle));
  316.                 aSectHandle^^.fSectHandle := aSectionHandle;
  317.                 SetERefCon(aSectionHandle, aSectHandle);
  318.                 
  319.                 anAlias := AliasHandle(Get1Resource(rAliasType, aSectHandle^^.fSectionID));
  320.                 err     := HandtoHand(Handle(anAlias));
  321.                 aSectionHandle^^.alias := anAlias;
  322.                 
  323.                 {now register the section}
  324.                 
  325.                 err := ResolveAlias(NIL, aSectionHandle^^.alias, myFSSpec, ignore);
  326.                 IF err <> noErr THEN
  327.                     BEGIN
  328.                         ShowError('Resolve Alias', err);
  329.                         Exit(ReadASection);
  330.                     END;
  331.                     
  332.                 err := RegisterSection(myFSSpec, aSectionHandle, ignore);
  333.                 
  334.                 IF (err <> noErr) AND 
  335.                    (err <> notThePublisherWrn) AND
  336.                      (err <> multiplePublisherWrn) THEN
  337.                     BEGIN
  338.                         ShowError('RegisterSection', err);
  339.                         Exit(ReadASection);
  340.                     END;
  341.                 SetSelectionRgn(aSectHandle^^.fDocument^.theText, aSectHandle^^.fStart, aSectHandle^^.fEnd,
  342.                                                 aSectHandle^^.fBorderRgn);
  343.                 InvalRgn(aSectHandle^^.fBorderRgn);
  344.             END;
  345.  
  346.     {*-----------------------------------------------------------------------
  347.         Name:             ReadAllSectionResources
  348.         Purpose:        Call the above routine to read in the resources for
  349.                                 each section in the document.
  350.     -----------------------------------------------------------------------*}
  351.         {$S Editions}
  352.  
  353.         PROCEDURE ReadAllSectionResources(aDoc: DPtr);
  354.  
  355.             VAR
  356.                 theSection        : SectHandle;
  357.  
  358.             BEGIN
  359.                 {read in each section resource}
  360.                 theSection := aDoc^.firstSection;
  361.                 WHILE theSection <> NIL DO
  362.                     BEGIN
  363.                         ReadASection(theSection);
  364.                         theSection := theSection^^.fNextSection;
  365.                     END;
  366.             END;
  367.  
  368.  {*-----------------------------------------------------------------------
  369.         Name:             ReadSectionRecords
  370.         Purpose:        Read in all the 'sect' resources and form list
  371.                                 of sections in the document.    This is called from the
  372.                                 main read document routine.
  373.     -----------------------------------------------------------------------*}
  374.         {$S Editions}
  375.  
  376.         PROCEDURE ReadSectionRecords(aDoc: DPtr);
  377.  
  378.             VAR
  379.                 theID                 : INTEGER;
  380.                 aSectHandle     : SectHandle;
  381.                 err                     : OSErr;
  382.                 theCount            : INTEGER;
  383.  
  384.             BEGIN
  385.                 {read in all the 'sect' resources for our document's sections}
  386.                 theCount := aDoc^.numSections;
  387.                 IF theCount = 0 THEN
  388.                     Exit(ReadSectionRecords);
  389.                 aDoc^.numSections := 0;
  390.                 FOR theID := 1 TO theCount DO
  391.                     BEGIN
  392.                         aSectHandle := SectHandle(Get1Resource('SECT', theID));
  393.                         err := HandtoHand(Handle(aSectHandle));
  394.                         {now add it to the list}
  395.                         IF aSectHandle <> NIL THEN
  396.                             AddSection(aSectHandle, aDoc);
  397.                         {here we should recalculate the region for the bounds}
  398.                         aSectHandle^^.fBorderRgn := NewRgn;
  399.                         { Bug fix : fill in the fdocument field }
  400.                         aSectHandle^^.fDocument  := aDoc;
  401.                     END;
  402.                 {set numsections to NIL, so we can get an accurate result from AddSection}
  403.             END;
  404.  
  405. {*-----------------------------------------------------------------------
  406.         Name:             SaveASection
  407.         Purpose:        Write out the 'sect', rAliasType and rSectionType resources
  408.                                 to file.    Called when the document is saved.
  409.     -----------------------------------------------------------------------*}
  410.  
  411.         {$S Editions}
  412.  
  413.         PROCEDURE SaveASection(aSection: SectHandle;
  414.                                                      count: INTEGER);
  415.  
  416.             VAR
  417.                 EMSection         : SectionHandle;
  418.                 err                     : OSErr;
  419.                 tempHandle        : Handle;
  420.  
  421.             BEGIN
  422.                 HLock(Handle(aSection));
  423.                 {save this section as its component rAliasType and rSectionType resource}
  424.                 {also save as our own section record as a 'sect' resource}
  425.                 EMSection := aSection^^.fSectHandle;
  426.                 tempHandle := Handle(EMSection);
  427.                 err := HandtoHand(tempHandle);
  428.                 HLock(Handle(EMSection));
  429.                 AddResource(tempHandle, rSectionType, EMSection^^.sectionID, '');
  430.                 err := ResError;
  431.                 IF err <> noErr THEN
  432.                     BEGIN
  433.                         ShowError('AddResource- rSectionType', err);
  434.                         Exit(SaveASection);
  435.                     END;
  436.  
  437.                 {now add the alias resource}
  438.                 tempHandle := Handle(EMSection^^.alias);
  439.                 err := HandtoHand(tempHandle);
  440.                 AddResource(tempHandle, rAliasType, EMSection^^.sectionID, '');
  441.                 IF err <> noErr THEN
  442.                     BEGIN
  443.                         ShowError('AddResource- rAliasType', err);
  444.                         Exit(SaveASection);
  445.                     END;
  446.  
  447.                 {now add our own resource- for now all the record, although we only need a few fields}
  448.                 tempHandle := Handle(aSection);
  449.                 err := HandtoHand(tempHandle);
  450.                 AddResource(tempHandle, 'SECT', count, '');
  451.                 IF err <> noErr THEN
  452.                     BEGIN
  453.                         ShowError('AddResource- SECT', err);
  454.                         Exit(SaveASection);
  455.                     END;
  456.  
  457.                 HUnlock(Handle(aSection));
  458.                 HUnlock(Handle(EMSection));
  459.             END;
  460.  
  461.  {*-----------------------------------------------------------------------
  462.         Name:             SaveSections
  463.         Purpose:        Called to go down to the section list and call SaveASection
  464.                                 for each one.
  465.     -----------------------------------------------------------------------*}
  466.  
  467.         {$S Editions}
  468.  
  469.         PROCEDURE SaveSections(aDocument: DPtr);
  470.  
  471.             VAR
  472.                 err                     : OSErr;
  473.                 currSection     : SectHandle;
  474.                 count                 : INTEGER;
  475.  
  476.             BEGIN
  477.                 {go down the list and save each of the sections}
  478.                 {the resource file is already open for writing}
  479.                 count := 1;
  480.                 err := ResError;
  481.                 IF err <> noErr THEN
  482.                     BEGIN
  483.                         ShowError('HOpenResFile', err);
  484.                         Exit(SaveSections);
  485.                     END;
  486.  
  487.                 {now go down the list}
  488.                 currSection := aDocument^.firstSection;
  489.                 WHILE currSection <> NIL DO
  490.                     BEGIN
  491.                         SaveASection(currSection, count);
  492.                         currSection := currSection^^.fNextSection;
  493.                         count := count + 1;
  494.                     END;
  495.             END;
  496.  
  497.  {*-----------------------------------------------------------------------
  498.         Name:             AssocAllSections
  499.         Purpose:        Associate all the sections in a document with the document.
  500.                                 Called on a SaveAs.
  501.     -----------------------------------------------------------------------*}
  502.  
  503.         {$S Editions}
  504.  
  505.         PROCEDURE AssocAllSections(theDoc: DPtr);
  506.  
  507.             VAR
  508.                 aSection            : SectHandle;
  509.                 EMSection         : SectionHandle;
  510.                 err                     : OSErr;
  511.  
  512.             BEGIN
  513.                 {called by DoSaveAs.    Make sure sections are registered with this document}
  514.                 aSection := theDoc^.firstSection;
  515.                 WHILE aSection <> NIL DO
  516.                     BEGIN
  517.                         EMSection := aSection^^.fSectHandle;
  518.                         err := AssociateSection(EMSection, @theDoc^.theFSSpec);
  519.                         aSection := aSection^^.fNextSection;
  520.                     END;
  521.             END;
  522.  
  523.             
  524. {*-----------------------------------------------------------------------
  525.         Name:             KeyOKinSubscriber
  526.         Purpose:        Detects arrow keys.
  527.  -----------------------------------------------------------------------*}
  528.     (*$S Editions*)
  529.     
  530.     FUNCTION KeyOKinSubscriber(whatKey:Char):BOOLEAN;
  531.         CONST kChLeft        = 28;
  532.                     kChRight    = 29;
  533.                     kChUp            = 30;
  534.                     kChDown        = 31;
  535.         
  536.         BEGIN
  537.             KeyOKinSubscriber := (whatKey=CHR(kChUp)) OR
  538.                                  (whatKey=CHR(kChDown)) OR
  539.                                                      (whatKey=CHR(kChLeft)) OR
  540.                                                      (whatKey=CHR(kChRight));
  541.             
  542.         END; (*KeyOKinSubscriber*)
  543.  
  544. {*-----------------------------------------------------------------------
  545.         Name:             ShiftSection
  546.         Purpose:        Moves a section by howMany characters.
  547.  -----------------------------------------------------------------------*}
  548.  
  549.         PROCEDURE ShiftSection(whichSection:SectHandle; howMany:INTEGER);
  550.             BEGIN
  551.                 whichSection^^.fStart := whichSection^^.fStart + howMany;
  552.                 whichSection^^.fEnd   := whichSection^^.fEnd   + howMany;
  553.             END; (* ShiftSection *)
  554.             
  555. {*-----------------------------------------------------------------------
  556.         Name:             DoSectionRecalc
  557.         Purpose:        Keeps track of the positions of the sections.
  558.  -----------------------------------------------------------------------*}
  559.  
  560.         {$S Editions}
  561.  
  562.         PROCEDURE DoSectionRecalc(theDoc : DPtr; toAdd:INTEGER);
  563.             VAR
  564.                 theStartPos         : INTEGER;
  565.                 theEndPos           : INTEGER;
  566.                 aSection                : SectHandle;
  567.                 oldSectionStart : INTEGER;
  568.                 oldSectionEnd   : INTEGER;
  569.                 wasChanged            : Boolean;
  570.                 oldPort                    : GrafPtr;
  571.                 
  572.             BEGIN
  573.                 (*
  574.                     Work thru all sections -
  575.                     1) Those spanning area of modification get modified or zapped
  576.                     2) Those after get shifted back or forwards.
  577.                     
  578.                     Sorry it is so complicated - there's a lot of possibilities
  579.                 *)
  580.                 theStartPos := theDoc^.theText^^.selStart;
  581.                 theEndPos   := theDoc^.theText^^.selEnd;
  582.                 
  583.                 aSection := theDoc^.firstSection;
  584.                 WHILE (aSection <> NIL) DO
  585.                     BEGIN
  586.                         wasChanged := TRUE;
  587.                         
  588.                         oldSectionEnd   := aSection^^.fEnd;
  589.                         oldSectionStart := aSection^^.fStart;
  590.                         
  591.                         IF (theEndPos < aSection^^.fStart) THEN
  592.                             ShiftSection(aSection, toAdd - (theEndPos-theStartPos))
  593.                         ELSE
  594.                             IF (theStartPos = aSection^^.fStart) THEN
  595.                                 IF (theEndPos = aSection^^.fStart) THEN
  596.                                     ShiftSection(aSection, toAdd - (theEndPos-theStartPos))
  597.                                 ELSE
  598.                                     IF (theEndPos >= aSection^^.fEnd) THEN (* section becomes pasted text *)
  599.                                         aSection^^.fEnd := aSection^^.fStart + toAdd 
  600.                                     ELSE                                                                    (* insert pasted text *)
  601.                                         aSection^^.fEnd := aSection^^.fEnd + toAdd - (theEndPos-theStartPos)
  602.                             ELSE
  603.                                 IF (theStartPos< aSection^^.fStart) THEN
  604.                                     aSection^^.fStart := theStartPos + toAdd (* move start to end of pasted text *)
  605.                                 ELSE
  606.                                     IF (theStartPos <= aSection^^.fEnd) THEN
  607.                                         IF (theEndPos >= aSection^^.fEnd) THEN (* end of section becomes pasted text *)
  608.                                             aSection^^.fEnd := theStartPos + toAdd 
  609.                                         ELSE                                                                    (* insert pasted text into section *)
  610.                                             aSection^^.fEnd := aSection^^.fEnd + toAdd - (theEndPos-theStartPos)
  611.                                     ELSE
  612.                                         wasChanged := FALSE;
  613.                         
  614.                         IF wasChanged THEN
  615.                             BEGIN
  616.                                 aSection^^.fCount := aSection^^.fEnd - aSection^^.fStart;
  617.                                 
  618.                                 IF theDoc^.showBorders THEN
  619.                                     BEGIN (* Force an update of the borders - later*)
  620.                                         GetPort(oldPort);
  621.                                         SetPort(theDoc^.theWindow);
  622.                                         
  623.                                         SetSelectionRgn(theDoc^.theText,
  624.                                                                         oldSectionStart,
  625.                                                                         oldSectionEnd,
  626.                                                                         aSection^^.fBorderRgn);
  627.                                         InvalRgn(aSection^^.fBorderRgn);
  628.                                         
  629.                                         SetPort(oldPort);
  630.                                     END;
  631.                                     
  632.                                 END;
  633.  
  634.                         aSection := aSection^^.fNextSection;
  635.                     END;
  636.             END; (* DoSectionRecalc *)
  637.             
  638.  {*-----------------------------------------------------------------------
  639.         Name:             ReadAnEdition
  640.         Purpose:        Read the latest version of an edition from disk.
  641.     -----------------------------------------------------------------------*}
  642.  
  643.         {$S Editions}
  644.  
  645.         PROCEDURE ReadAnEdition(mySectHdl: SectionHandle);
  646.             VAR
  647.                 aSectHandle     : SectHandle;
  648.                 theRefNum         : EditionRefNum;
  649.                 err                     : OSErr;
  650.                 p                         : Ptr;
  651.                 theStylHandle : Handle;
  652.                 cutSize             : LONGINT;
  653.                 stylSize            : LONGINT;
  654.                 stylErr                : OsErr;
  655.                 
  656.             BEGIN
  657.                 p := NIL;
  658.                 theStylHandle := NIL;
  659.                 
  660.                 IF mySectHdl = NIL THEN
  661.                     BEGIN
  662.                         ShowError('mySectHdl is NIL', 0);
  663.                         Exit(ReadAnEdition);
  664.                     END;
  665.  
  666.                 aSectHandle := SectHandle(GetERefCon(mySectHdl));
  667.                 IF aSectHandle = NIL THEN
  668.                     BEGIN
  669.                         ShowError('aSectHandle is NIL', 0);
  670.                         Exit(ReadAnEdition);
  671.                     END;
  672.  
  673.                 GetDateTime(mySectHdl^^.mdDate);
  674.  
  675.                 {read a subscriber in from disk.    Usually in response to a sectionread event}
  676.                 err := OpenEdition(mySectHdl, theRefNum);
  677.  
  678.                 IF err <> noErr THEN
  679.                     BEGIN
  680.                         ShowError('OpenEdition in ReadAnEdition', err);
  681.                         Exit(ReadAnEdition);
  682.                     END;
  683.  
  684.                 err := EditionHasFormat(theRefNum, 'TEXT', cutSize);
  685.                 IF err <> noErr THEN
  686.                     BEGIN
  687.                         ShowError('EditionHasFormat', err);
  688.                         Exit(ReadAnEdition);
  689.                     END;
  690.                     
  691.                 stylErr := EditionHasFormat(theRefNum, 'styl', stylSize);
  692.  
  693.                 err := SetEditionFormatMark(theRefNum, 'TEXT', 0);
  694.                 IF err <> noErr THEN
  695.                     BEGIN
  696.                         ShowError('SetEditionFormatMark', err);
  697.                         Exit(ReadAnEdition);
  698.                     END;
  699.  
  700.                 {set up a buffer for the text we're going to read in}
  701.                 p := NewPtr(cutSize);
  702.                 IF (p = NIL) THEN
  703.                     BEGIN
  704.                         ShowError('Insufficient memory to read edition', MemError);
  705.                         Exit(ReadAnEdition);
  706.                     END;
  707.                     
  708.                 err := ReadEdition(theRefNum, 'TEXT', p, cutSize);
  709.  
  710.                 IF (err <> noErr) THEN
  711.                     BEGIN
  712.                         ShowError('ReadEdition', err);
  713.                         Exit(ReadAnEdition);
  714.                     END;
  715.                     
  716.                 IF (stylErr = noErr) THEN
  717.                     BEGIN
  718.                         theStylHandle := NewHandle(stylSize);
  719.                         stylErr := SetEditionFormatMark(theRefNum, 'styl', 0);
  720.                         IF (stylErr = noErr) THEN
  721.                             IF (theStylHandle<>NIL) THEN
  722.                                 BEGIN
  723.                                     HLock(theStylHandle);
  724.                                     stylErr := ReadEdition(theRefNum, 'styl', theStylHandle^, stylSize);
  725.                                     HUnLock(theStylHandle);
  726.                                 END;
  727.                     END;
  728.  
  729.                 err := CloseEdition(theRefNum, TRUE);
  730.                 IF err <> noErr THEN
  731.                     BEGIN
  732.                         ShowError('CloseEdition', err);
  733.                         Exit(ReadAnEdition);
  734.                     END;
  735.                     
  736.                 (*
  737.                     Ensure this section has a region and invalidate the old region
  738.                 *)
  739.                 
  740.                 IF (aSectHandle^^.fBorderRgn = NIL) THEN
  741.                     aSectHandle^^.fBorderRgn := NewRgn;
  742.  
  743.                 SetSelectionRgn(aSectHandle^^.fDocument^.theText,
  744.                                                 aSectHandle^^.fStart,
  745.                                                 aSectHandle^^.fEnd,
  746.                                                 aSectHandle^^.fBorderRgn);
  747.                                                 
  748.                 InvalRgn(aSectHandle^^.fBorderRgn);
  749.                 
  750.                 {now insert the text in the right place by setting the selection range}
  751.                 {we want this to act like paste, but without putting the contents on the clipboard}
  752.                 {so we have to delete the current selection range and then insert our new text}
  753.                 
  754.                 (*
  755.                     Also fixup section info. for other moved sections
  756.                 *)
  757.  
  758.                 TESetSelect(aSectHandle^^.fStart,
  759.                                         aSectHandle^^.fEnd,
  760.                                         aSectHandle^^.fDocument^.theText);
  761.                                         
  762.                 DoSectionRecalc(aSectHandle^^.fDocument,
  763.                                 cutSize);
  764.                                                 
  765.                 TEDelete(aSectHandle^^.fDocument^.theText);
  766.                 TEStylInsert(p, cutSize, StScrpHandle(theStylHandle), aSectHandle^^.fDocument^.theText);
  767.  
  768.                 (*
  769.                     Now a little fix up - if the section was previously empty the
  770.                     DoSectionRecalc will have put the text in before the section.
  771.                     It's like that so you can type in before a subscriber in an
  772.                     otherwise empty document. So now pull the start of this section
  773.                     back to include the text we just added.
  774.                 *)
  775.                 
  776.                 aSectHandle^^.fStart := aSectHandle^^.fEnd - cutSize;
  777.                 
  778.                 (*
  779.                     Force redraw of this region
  780.                 *)
  781.                 
  782.                 SetSelectionRgn(aSectHandle^^.fDocument^.theText,
  783.                                                 aSectHandle^^.fStart,
  784.                                                 aSectHandle^^.fEnd,
  785.                                                 aSectHandle^^.fBorderRgn);
  786.                                                 
  787.                 InvalRgn(aSectHandle^^.fBorderRgn);
  788.                 
  789.                 DisposPtr(p);
  790.                 
  791.                 IF (theStylHandle<>NIL) THEN
  792.                     DisposHandle(theStylHandle);
  793.             END;
  794.  
  795.  {*-----------------------------------------------------------------------
  796.         Name:             WriteAnEdition
  797.         Purpose:        Write out the latest version of an Edition.
  798.                                 Called on a Save and on selecting WriteEdition now from
  799.                                 the Publisher Options dialog.
  800.     -----------------------------------------------------------------------*}
  801.  
  802.         {$S Editions}
  803.  
  804.         PROCEDURE WriteAnEdition(mySectHdl: SectionHandle);
  805.  
  806.             VAR
  807.                 err                     : OSErr;
  808.                 aSectHandle     : SectHandle;
  809.                 theRefNum         : EditionRefNum;
  810.                 aHandle             : Handle;
  811.                 theStylHandle : StScrpHandle;
  812.                 oldSelStart   : INTEGER;
  813.                 oldSelEnd     : INTEGER;
  814.                 theFSSpecPtr  : FSSpecPtr;
  815.                 
  816.             BEGIN
  817.                 aSectHandle := SectHandle(GetERefCon(mySectHdl));
  818.                 {alter the modification date for the section}
  819.                 GetDateTime(mySectHdl^^.mdDate);
  820.                 {write out the edition.  Assume that it is a publisher for now}
  821.                 {subscribers will be opened for writing with OpenEdition}
  822.                 
  823.                 IF (aSectHandle^^.fDocument^.everSaved = FALSE)  THEN
  824.                     theFSSpecPtr := NIL
  825.                 ELSE
  826.                     theFSSpecPtr := @aSectHandle^^.fDocument^.theFSSpec;
  827.                     
  828.                 err := OpenNewEdition(mySectHdl,
  829.                                                             'SVED',
  830.                                                             theFSSpecPtr,
  831.                                                             theRefNum);
  832.                 IF err <> noErr THEN
  833.                     BEGIN
  834.                         ShowError('OpenNewEdition', err);
  835.                         Exit(WriteAnEdition);
  836.                     END;
  837.  
  838.                 err := SetEditionFormatMark(theRefNum, 'TEXT', 0);
  839.                 IF err <> noErr THEN
  840.                     BEGIN
  841.                         ShowError('SetEditionFormatMark', err);
  842.                         Exit(WriteAnEdition);
  843.                     END;
  844.  
  845.                 {now get a handle to the text to be written out}
  846.                 {use the same start and end positions for now, increasing and decreasing}
  847.                 {the selection will be implemented later}
  848.  
  849.                 aHandle := GetHandleToText(aSectHandle^^.fDocument^.theText,
  850.                                                                      aSectHandle^^.fStart,
  851.                                                                      aSectHandle^^.fEnd);
  852.                 HLock(aHandle);
  853.  
  854.                 {make sure the count is up to date}
  855.                 aSectHandle^^.fCount := aSectHandle^^.fEnd - aSectHandle^^.fStart;
  856.  
  857.                 err := WriteEdition(theRefNum, 'TEXT', aHandle^, aSectHandle^^.fCount);
  858.                 IF err <> noErr THEN
  859.                     BEGIN
  860.                         ShowError('WriteEdition', err);
  861.                         Exit(WriteAnEdition);
  862.                     END;
  863.                 HUnlock(aHandle);
  864.                 
  865.                 oldSelStart   := aSectHandle^^.fDocument^.theText^^.selStart;
  866.                 oldSelEnd     := aSectHandle^^.fDocument^.theText^^.selEnd;
  867.                 
  868.                 TESetSelect(aSectHandle^^.fStart,aSectHandle^^.fEnd, aSectHandle^^.fDocument^.theText);
  869.                 theStylHandle := GetStylScrap(aSectHandle^^.fDocument^.theText);
  870.                 TESetSelect(oldSelStart,oldSelEnd, aSectHandle^^.fDocument^.theText);
  871.                 
  872.                 IF (theStylHandle<>NIL) THEN
  873.                     BEGIN
  874.                         err := SetEditionFormatMark(theRefNum, 'styl', 0);
  875.                         IF err <> noErr THEN
  876.                             BEGIN
  877.                                 ShowError('SetEditionFormatMark for styl', err);
  878.                                 Exit(WriteAnEdition);
  879.                             END;
  880.                         HLock(Handle(theStylHandle));
  881.                         
  882.                         err := WriteEdition(theRefNum,
  883.                                                                 'styl',
  884.                                                                 Ptr(theStylHandle^),
  885.                                                                 GetHandleSize(Handle(theStylHandle)));
  886.                         HUnLock(Handle(theStylHandle));
  887.                     END;
  888.                     
  889.                 {remember to save the section and alias records as resources later}
  890.                 
  891.                 {now close the edition}
  892.                 
  893.                 err := CloseEdition(theRefNum, TRUE);
  894.                 IF err <> noErr THEN
  895.                     BEGIN
  896.                         ShowError('CloseEdition', err);
  897.                         Exit(WriteAnEdition);
  898.                     END;
  899.  
  900.                 (*
  901.                     Clean Up
  902.                 *)
  903.                 
  904.                 DisposHandle(aHandle);
  905.                 IF (theStylHandle<>NIL) THEN
  906.                     DisposHandle(Handle(theStylHandle));    
  907.                 
  908.             END;                 {WriteAnEdition}
  909.  
  910.  {*-----------------------------------------------------------------------
  911.         Name:             WriteAllEditions
  912.         Purpose:        Go down the list and call WriteAnEdition
  913.     -----------------------------------------------------------------------*}
  914.  
  915.         {$S Editions}
  916.  
  917.         PROCEDURE WriteAllEditions(aDocument: DPtr);
  918.  
  919.             VAR
  920.                 aSection            : SectHandle;
  921.                 EMSection         : SectionHandle;
  922.                 err                     : OSErr;
  923.  
  924.             BEGIN
  925.                 {called on a Save, to write out all editions}
  926.                 aSection := aDocument^.firstSection;
  927.                 WHILE aSection <> NIL DO
  928.                     BEGIN
  929.                         EMSection := aSection^^.fSectHandle;
  930.                         IF EMSection^^.kind = stPublisher THEN
  931.                             WriteAnEdition(EMSection);
  932.                         aSection := aSection^^.fNextSection;
  933.                     END;
  934.             END;
  935.  
  936.  {*-----------------------------------------------------------------------
  937.         Name:             DeRegisterAllSections
  938.         Purpose:        Called on cancel Publisher/Subscriber and on a close.
  939.     -----------------------------------------------------------------------*}
  940.  
  941.         {$S Editions}
  942.  
  943.         PROCEDURE DeRegisterAllSections(aDoc: DPtr);
  944.  
  945.             VAR
  946.                 aSection            : SectHandle;
  947.                 EMSection         : SectionHandle;
  948.                 err                     : OSErr;
  949.  
  950.             BEGIN
  951.                 aSection := aDoc^.firstSection;
  952.                 WHILE aSection <> NIL DO
  953.                     BEGIN
  954.                         EMSection := aSection^^.fSectHandle;
  955.                         err := UnRegisterSection(EMSection);
  956.                         aSection := aSection^^.fNextSection;
  957.                     END;
  958.             END;
  959.  
  960. {*-----------------------------------------------------------------------
  961.         Name:             GetHandleToText
  962.         Purpose:        Get a handle to the current text selection.
  963.                                 Used to provide a preview on Create Publisher...
  964.     -----------------------------------------------------------------------*}
  965.  
  966.         {$S Editions}
  967.  
  968.         FUNCTION GetHandleToText(aTEHandle: TEHandle;
  969.                                                          theStart, theEnd: INTEGER): Handle;
  970.  
  971.             VAR
  972.                 err                     : OSErr;
  973.                 myHandle            : Handle;
  974.                 p                         : PTR;
  975.  
  976.             BEGIN
  977.                 HLock(aTEHandle^^.hText);
  978.                 p := aTEHandle^^.hText^;
  979.                 p := POINTER(ORD4(p) + (theStart));
  980.                 err := PtrToHand(p, myHandle, (theEnd - theStart));
  981.                 HUnlock(aTEHandle^^.hText);
  982.                 GetHandleToText := myHandle;
  983.             END; (* GetHandleToText *)
  984.  
  985. {*-----------------------------------------------------------------------
  986.         Name:             FindLine
  987.         Purpose:        Find the line a character is in.
  988.                                 Used to find to calculate the region to use for the Publisher/
  989.                                 Subscriber borders.
  990.     -----------------------------------------------------------------------*}
  991.  
  992.         {$S Editions}
  993.  
  994.         FUNCTION FindLine(thePos: INTEGER;
  995.                                             theTEHandle: TEHandle): INTEGER;
  996.  
  997.             VAR
  998.                 Index                 : INTEGER;
  999.                 theFirstPos, theNextPos: INTEGER;
  1000.  
  1001.             BEGIN
  1002.                 Index := 0;
  1003.  
  1004.                 REPEAT
  1005.                     BEGIN
  1006.                         theFirstPos := theTEHandle^^.LineStarts[Index];
  1007.                         theNextPos := theTEHandle^^.LineStarts[Index + 1];
  1008.                         Index := Index + 1;
  1009.                     END;
  1010.                 UNTIL (((thePos >= theFirstPos) AND (thePos < theNextPos)) OR (Index >
  1011.                             theTEHandle^^.nLines));
  1012.                 FindLine := Index;
  1013.             END;
  1014.  
  1015. {*-----------------------------------------------------------------------
  1016.         Name:             DrawSelectionRgn
  1017.         Purpose:        Given a text handle and a start and end position this routine
  1018.                                 will draw a section border around the selected text.
  1019.                                 Must allow for the case when the section has no text in it-
  1020.                                 but we still want to show it as a published section
  1021.  -----------------------------------------------------------------------*}
  1022.  
  1023.  PROCEDURE DrawSelectionRegion(theTEHandle : TEHandle;
  1024.                                                              posStart         : INTEGER;
  1025.                                                            posEnd             : INTEGER);                
  1026.                                                              
  1027.      VAR theSelRgn : RgnHandle;
  1028.     
  1029.     BEGIN
  1030.     theSelRgn := NewRgn;
  1031.         
  1032.         SetSelectionRgn(theTEHandle,posStart, posEnd,theSelRgn);
  1033.         FrameRgn(theSelRgn);
  1034.         
  1035.         DisposeRgn(theSelRgn);
  1036.         
  1037.     END; (* DrawSelectionRegion *)
  1038.     
  1039. {*-----------------------------------------------------------------------
  1040.         Name:             SetSelectionRgn
  1041.         Purpose:        Given a text handle and a start and end position this routine
  1042.                                 will return the region which is necessary to draw a section
  1043.                                 border around the selected text.
  1044.                                 Must allow for the case when the section has no text in it-
  1045.                                 but we still want to show it as a published section
  1046.  -----------------------------------------------------------------------*}
  1047.  
  1048.         {$S Editions}
  1049.  
  1050.         PROCEDURE SetSelectionRgn(theTEHandle: TEHandle;
  1051.                                                             posStart, posEnd: INTEGER;
  1052.                                                             VAR theSelRgn: RgnHandle);
  1053.  
  1054.             VAR
  1055.                 theStart            : Point;
  1056.                 theEnd                : Point;
  1057.                 startLine         : INTEGER;
  1058.                 endLine             : INTEGER;
  1059.                 theRect             : RECT;
  1060.                 theLeft             : INTEGER;
  1061.                 theRight            : INTEGER;
  1062.                 theBottom         : INTEGER;
  1063.                 theTop                : INTEGER;
  1064.                 slineHeight     : INTEGER;
  1065.                 elineHeight     : INTEGER;
  1066.                 theTStyle         : TextStyle;
  1067.                 fontAscent        : INTEGER;
  1068.  
  1069.             BEGIN
  1070.                 {first of all find out if the text is on the same line}
  1071.                 startLine := FindLine(posStart, theTEHandle);
  1072.                 endLine := FindLine(posEnd, theTEHandle);
  1073.  
  1074.                 theStart := TEGetPoint(posStart, theTEHandle);
  1075.                 theEnd   := TEGetPoint(posEnd, theTEHandle);
  1076.  
  1077.      (*
  1078.         Get the line height info
  1079.      *)
  1080.                 TEGetStyle(posStart, theTStyle, slineHeight, fontAscent, theTEHandle);
  1081.                 TEGetStyle(posEnd, theTStyle, elineHeight, fontAscent, theTEHandle);
  1082.  
  1083.                 IF startLine = endLine THEN
  1084.                     BEGIN
  1085.                         {use the start and end points to form the rectangle and draw this into the region}
  1086.                         theStart.v := theStart.v - slineHeight;
  1087.                         Pt2Rect(theStart, theEnd, theRect);
  1088.                         InsetRect(theRect, - 1, - 1);
  1089.                         RectRgn(theSelRgn, theRect);
  1090.                     END
  1091.                 ELSE
  1092.                     BEGIN
  1093.                         theLeft  := theTEHandle^^.destRect.left;
  1094.                         theRight := theTEHandle^^.destRect.right;
  1095.                         theTop := theStart.v - slineHeight;
  1096.                         theBottom := theEnd.v;
  1097.                         OpenRgn;
  1098.                         MoveTo(theStart.h, theStart.v - slineHeight);
  1099.                         LineTo(theRight, theStart.v - slineHeight);
  1100.                         LineTo(theRight, theEnd.v - elineHeight);
  1101.                         LineTo(theEnd.h, theEnd.v - elineHeight);
  1102.                         LineTo(theEnd.h, theEnd.v);
  1103.                         LineTo(theLeft, theEnd.v);
  1104.                         LineTo(theLeft, theStart.v);
  1105.                         LineTo(theStart.h, theStart.v);
  1106.                         LineTo(theStart.h, theStart.v - slineHeight);
  1107.                         CloseRgn(theSelRgn);
  1108.                     END;
  1109.  
  1110.                 InsetRgn(theSelRgn, - 2, - 2);
  1111.  
  1112.             END;
  1113.  
  1114. {*-----------------------------------------------------------------------
  1115.         Name:             ShowSectionBorders
  1116.         Purpose:        Show the borders for all the sections in a document.
  1117.                                 Show a Publisher border in 50% gray, a subscriber in 75% gray
  1118.  -----------------------------------------------------------------------*}
  1119.  
  1120.         {$S Editions}
  1121.  
  1122.         PROCEDURE ShowSectionBorders(aDoc: DPtr);
  1123.  
  1124.             VAR
  1125.                 aSection            : SectHandle;
  1126.  
  1127.             BEGIN
  1128.                 PenNormal;
  1129.                 PenSize(3, 3);
  1130.                 PenPat(Gray);
  1131.                 aSection := aDoc^.firstSection;
  1132.                 WHILE aSection <> NIL DO
  1133.                     BEGIN
  1134.                         IF aSection^^.fBorderRgn <> NIL THEN
  1135.                             BEGIN
  1136.                                 SetSelectionRgn(aSection^^.fDocument^.theText, 
  1137.                                                                 aSection^^.fStart, 
  1138.                                                                 aSection^^.fEnd,
  1139.                                                                 aSection^^.fBorderRgn);
  1140.                                                                 
  1141.                                 IF aSection^^.fSectHandle^^.kind = stPublisher THEN
  1142.                                     PenPat(Gray)
  1143.                                 ELSE
  1144.                                     PenPat(dkGray);
  1145.                                     
  1146.                                 FrameRgn(aSection^^.fBorderRgn);
  1147.                                 PenNormal;
  1148.                             END;
  1149.                         aSection := aSection^^.fNextSection;
  1150.                     END;
  1151.                 PenNormal;
  1152.             END;
  1153.  
  1154. {*-----------------------------------------------------------------------
  1155.         Name:             RecalcBorders
  1156.         Purpose:        Recalculate all the borders for the sections in a document.
  1157.  -----------------------------------------------------------------------*}
  1158.  
  1159.         {$S Editions}
  1160.  
  1161.         PROCEDURE RecalcBorders(aDoc: DPtr;
  1162.                                                         invalidate: BOOLEAN);
  1163.  
  1164.             VAR
  1165.                 aSection            : SectHandle;
  1166.  
  1167.             BEGIN
  1168.                 {go down the section list and recalculate all the borders}
  1169.                 aSection := aDoc^.firstSection;
  1170.                 WHILE aSection <> NIL DO
  1171.                     BEGIN
  1172.                         IF aSection^^.fBorderRgn <> NIL THEN
  1173.                             BEGIN
  1174.                                 IF invalidate THEN
  1175.                                     InvalRgn(aSection^^.fBorderRgn);
  1176.                                 SetSelectionRgn(aSection^^.fDocument^.theText, aSection^^.fStart, aSection^^.fEnd,
  1177.                                                                 aSection^^.fBorderRgn);
  1178.                                 IF invalidate THEN
  1179.                                     InvalRgn(aSection^^.fBorderRgn);
  1180.                             END;
  1181.                         aSection := aSection^^.fNextSection;
  1182.                     END;
  1183.             END;
  1184.  
  1185. {*-----------------------------------------------------------------------
  1186.         Name:             GetSection
  1187.         Purpose:        Given a start and end of a selection- return the section
  1188.                                 handle if it is in a Publisher or Subscriber.
  1189.  -----------------------------------------------------------------------*}
  1190.  
  1191.         {$S Editions}
  1192.  
  1193.         FUNCTION GetSection(theStartPos, theEndPos: INTEGER;
  1194.                                                 aDoc: DPtr): SectHandle;
  1195.  
  1196.             VAR
  1197.                 foundSection    : SectHandle;
  1198.                 aSection            : SectHandle;
  1199.  
  1200.             BEGIN
  1201.                 {returns the section handle for the section between theStartPos and theEndPos}
  1202.                 foundSection := NIL;
  1203.                 aSection := aDoc^.firstSection;
  1204.                 WHILE aSection <> NIL DO
  1205.                     BEGIN
  1206.                         IF ((theStartPos >= aSection^^.fStart) AND (theEndPos <= aSection^^.fEnd)) THEN
  1207.                             foundSection := aSection;
  1208.                         aSection := aSection^^.fNextSection;
  1209.                     END;
  1210.                 GetSection := foundSection;
  1211.             END;
  1212.  
  1213. {*-----------------------------------------------------------------------
  1214.         Name:             DoTEPasteSectionRecalc
  1215.         Purpose:        Keeps track of the positions of the sections call before a 
  1216.                     TEPaste or TEStylPaste.
  1217.  -----------------------------------------------------------------------*}
  1218.  
  1219.         PROCEDURE DoTEPasteSectionRecalc(theDoc : DPtr);
  1220.             VAR
  1221.                 toAdd       : INTEGER;
  1222.                 
  1223.             BEGIN
  1224.                 toAdd := TEGetScrapLen;
  1225.                 DoSectionRecalc(theDoc, toAdd);
  1226.             END; (* DoTEPasteSectionRecalc *)
  1227.             
  1228. {*-----------------------------------------------------------------------
  1229.         Name:             DoTEDeleteSectionRecalc
  1230.         Purpose:        Keeps track of the positions of the sections call before a 
  1231.                     TEDelete.
  1232.  -----------------------------------------------------------------------*}
  1233.  
  1234.         PROCEDURE DoTEDeleteSectionRecalc(theDoc : DPtr);
  1235.             BEGIN
  1236.                 DoSectionRecalc(theDoc, 0);
  1237.             END; (* DoTEDeleteSectionRecalc *)
  1238.             
  1239. {*-----------------------------------------------------------------------
  1240.         Name:             DoTECutSectionRecalc
  1241.         Purpose:        Keeps track of the positions of the sections call before a 
  1242.                     TECut.
  1243.  -----------------------------------------------------------------------*}
  1244.  
  1245.         PROCEDURE DoTECutSectionRecalc(theDoc : DPtr);
  1246.             BEGIN
  1247.                 DoSectionRecalc(theDoc, 0);
  1248.             END; (* DoTECutSectionRecalc *)
  1249.             
  1250. {*-----------------------------------------------------------------------
  1251.         Name:             DoTEKeySectionRecalc
  1252.         Purpose:        Keeps track of the positions of the sections call before a 
  1253.                     TECut.
  1254.  -----------------------------------------------------------------------*}
  1255.  
  1256.         PROCEDURE DoTEKeySectionRecalc(theDoc : DPtr; theChar:CHAR);
  1257.             VAR
  1258.                 toAdd       : INTEGER;
  1259.                 oldStart    : INTEGER;
  1260.                 
  1261.             BEGIN
  1262.                 IF NOT KeyOKinSubscriber(theChar) THEN (* is it a cursor motion key? - yes = ignore *)
  1263.                   BEGIN
  1264.                         IF theChar=CHR(8) THEN
  1265.                             IF (theDoc^.theText^^.selStart<theDoc^.theText^^.selEnd) THEN
  1266.                                 toAdd := 0
  1267.                             ELSE
  1268.                                 BEGIN
  1269.                                     toAdd := -1;
  1270.                                     oldStart := theDoc^.theText^^.selStart;
  1271.                                     
  1272.                                     theDoc^.theText^^.selStart := GreaterOf(oldStart-1,0);
  1273.                                     DoSectionRecalc(theDoc, 0);
  1274.                                     theDoc^.theText^^.selStart := oldStart;
  1275.                                 END
  1276.                         ELSE
  1277.                             toAdd := 1;
  1278.                             
  1279.                         IF (toAdd<>-1) THEN
  1280.                           DoSectionRecalc(theDoc, toAdd);
  1281.                     END;    
  1282.             END; (* DoTEKeySectionRecalc *)
  1283.  
  1284. {*-----------------------------------------------------------------------
  1285.         Name:             GetEditionContainer
  1286.         Purpose:        Gets the Edition Container to put the edition into.
  1287.                                 The main user interface stuff. 
  1288.                                 Puts up the new publisher dialog.
  1289.                                 Should check kAEInteractWithUser etc.
  1290.  -----------------------------------------------------------------------*}
  1291.  
  1292.         {$S Main}
  1293.  
  1294.         FUNCTION GetEditionContainer(theDoc: DPtr; VAR theFSSpec:FSSpec): OSErr;
  1295.  
  1296.             VAR
  1297.                 err                     : OSErr;
  1298.                 myReply             : NewPublisherReply;
  1299.                 theStart            : INTEGER;
  1300.                 theEnd                : INTEGER;
  1301.                 myHandle            : Handle;
  1302.  
  1303.             BEGIN                
  1304.                 err := noErr;
  1305.  
  1306.                 {get default editionContainer to use, using last volume and folder}
  1307.                 
  1308.                 myReply.container.thePart := kPartsNotUsed;
  1309.  
  1310.                 err := GetLastEditionContainerUsed(myReply.container);
  1311.                 
  1312.                 IF (err=fnfErr) THEN
  1313.                     err := noErr;
  1314.                 
  1315.                 theStart := theDoc^.theText^^.selStart;
  1316.                 theEnd   := theDoc^.theText^^.selEnd;
  1317.                                                 
  1318.                 IF (err=noErr) THEN    
  1319.                     BEGIN
  1320.                         {
  1321.                             Create a handle containing the text to be published for previewing -
  1322.                             need to ask the user where to put the data
  1323.                         }
  1324.                         myHandle := GetHandleToText(theDoc^.theText, theStart, theEnd);
  1325.                         
  1326.                         myReply.usePart       := FALSE;
  1327.                         myReply.preview       := myHandle;
  1328.                         myReply.previewFormat := 'TEXT';
  1329.                         myReply.container.theFile.name := ''; (* Want a proper prompted name here *)
  1330.                         HLock(myHandle);
  1331.                         
  1332.                         (* Should take suggested name and avoid dialog if no user interaction *)
  1333.                         
  1334.                         err := AEInteractWithUser(kAEDefaultTimeout, nil, nil);
  1335.                         
  1336.                         IF (err=noErr) THEN
  1337.                             err := NewPublisherDialog(myReply);
  1338.                         HUnlock(myHandle);
  1339.                         DisposHandle(myHandle);
  1340.                     END;
  1341.                     
  1342.                 {IF user cancelled, THEN exit from this routine}
  1343.                 
  1344.                 IF (err=noErr) THEN
  1345.                     IF (myReply.canceled) THEN
  1346.                         err := userCanceledErr; 
  1347.                     
  1348.                 IF (err=noErr) THEN
  1349.                     IF (myReply.replacing) THEN
  1350.                         err := FSpDelete(myReply.container.theFile);
  1351.                         
  1352.                 IF (err = noErr) THEN
  1353.                     theFSSpec := myReply.container.theFile;
  1354.                     
  1355.                 GetEditionContainer := err;
  1356.             END;                 {GetEditionContainer}
  1357.  
  1358.  
  1359. {*-----------------------------------------------------------------------
  1360.         Name:             PublishText
  1361.         Purpose:        Publishes the current selection of theDoc.
  1362.                                 The main user interface stuff. 
  1363.                                 Puts up the new publisher dialog - if theFSSpec=NIL
  1364.                                 Writes the new edition out to disk.
  1365.  -----------------------------------------------------------------------*}
  1366.  
  1367.         {$S Main}
  1368.  
  1369.         FUNCTION PublishText(theDoc: DPtr; theFSSpec:FSSpecPtr): OSErr;
  1370.  
  1371.             VAR
  1372.                 myReply             : NewPublisherReply;
  1373.                 mySectHdl         : SectionHandle;
  1374.                 err                     : OSErr;
  1375.                 mysectionID     : LONGINT;
  1376.                 pubFSSpec         : FSSpecPtr;
  1377.                 theStart            : INTEGER;
  1378.                 theEnd                : INTEGER;
  1379.                 theRgnHandle    : RgnHandle;
  1380.  
  1381.             BEGIN
  1382.                 
  1383.                 mysectionID    := theDoc^.lastID + 1;
  1384.                 theDoc^.lastID := mysectionID;
  1385.  
  1386.                 {get default editionContainer to use, using last volume and folder}
  1387.                 
  1388.                 myReply.container.thePart := kPartsNotUsed;
  1389.  
  1390.                 err := GetLastEditionContainerUsed(myReply.container);
  1391.                 
  1392.                 IF (err=fnfErr) THEN
  1393.                     err := noErr;
  1394.                 
  1395.                 theStart := theDoc^.theText^^.selStart;
  1396.                 theEnd   := theDoc^.theText^^.selEnd;
  1397.  
  1398.                 {don't want to publish an empty section}
  1399.                 
  1400.                 IF (theEnd - theStart = 0) THEN
  1401.                     err := userCanceledErr;
  1402.                     
  1403.                 myReply.container.theFile := theFSSpec^;
  1404.                     
  1405.                 {now publish this section}
  1406.                 
  1407.                 IF (err = noErr) THEN
  1408.                     err := CreateEditionContainerFile(myReply.container.theFile, 'SVED', 0);
  1409.                 
  1410.                 {check IF the file has been saved, IF not set pubCFS to NIL}
  1411.                 
  1412.                 IF (theDoc^.everSaved = FALSE) THEN
  1413.                     pubFSSpec := NIL
  1414.                 ELSE
  1415.                     pubFSSpec := @theDoc^.theFSSpec;
  1416.  
  1417.                 {get the region to encompass the selection}
  1418.                 
  1419.                 theRgnHandle := NewRgn;
  1420.                 SetSelectionRgn(theDoc^.theText, theDoc^.theText^^.selStart, theDoc^.theText^^.selEnd,
  1421.                                                 theRgnHandle);
  1422.                                                 
  1423.                 InvalRgn(theRgnHandle);
  1424.  
  1425.                 {create a publisher section}
  1426.                 IF (err=noErr) THEN
  1427.                     BEGIN
  1428.                         err := NewSection(myReply.container,
  1429.                                                             pubFSSpec,
  1430.                                                             stPublisher,
  1431.                                                             mysectionID,
  1432.                                                             pumOnSave,
  1433.                                                             mySectHdl);
  1434.         
  1435.                         {now add this section to our document list}
  1436.                         
  1437.                         IF (err = noErr) THEN
  1438.                             CreateSection(mySectHdl, mysectionID, theStart, theEnd, theDoc, theRgnHandle);
  1439.                     END;
  1440.  
  1441.                 {now write out the edition to file}
  1442.                 
  1443.                 IF (err=noErr) THEN
  1444.                     WriteAnEdition(mySectHdl);
  1445.                     
  1446.                 PublishText := err;
  1447.             END;                 {PublishText}
  1448.  
  1449. {*-----------------------------------------------------------------------
  1450.         Name:             DoSubscribe
  1451.         Purpose:        Subscribe to a published section. Puts up the subscriber
  1452.                                 dialog, creates and adds the new section.
  1453.  -----------------------------------------------------------------------*}
  1454.  
  1455.         {$S Main}
  1456.  
  1457.         PROCEDURE DoSubscribe(theDoc: DPtr);
  1458.  
  1459.             VAR
  1460.                 myReply             : NewSubscriberReply;
  1461.                 mySectHdl         : SectionHandle;
  1462.                 mysectionID     : LONGINT;
  1463.                 subFSSpec         : FSSpecPtr; {the fsspec for the subscriber file}
  1464.                 err                     : OSErr;
  1465.                 theStart            : INTEGER;
  1466.                 theEnd                : INTEGER;
  1467.  
  1468.             BEGIN
  1469.  
  1470.                 mysectionID := theDoc^.lastID + 1;
  1471.                 theDoc^.lastID := mysectionID;
  1472.                 err := noErr;
  1473.  
  1474.                 {get default editionContainer to use, using last volume and folder}
  1475.                 {  myreply.container.thePart := kPartNumberUnknown;}
  1476.                 myReply.formatsMask := kTEXTformatMask;
  1477.                 
  1478.                 err := GetLastEditionContainerUsed(myReply.container);
  1479.                 IF (err <> noErr) & (err <> fnfErr) THEN
  1480.                     BEGIN
  1481.                         ShowError('GetLastEditionContainerUsed', err);
  1482.                         Exit(DoSubscribe);
  1483.                     END;
  1484.  
  1485.                 {put up the subscriber dialog}
  1486.                 err := NewSubscriberDialog(myReply);
  1487.                 IF err <> noErr THEN
  1488.                     BEGIN
  1489.                         ShowError('NewSubscriberDialog', err);
  1490.                         Exit(DoSubscribe);
  1491.                     END;
  1492.  
  1493.                 {IF user cancelled, THEN exit from this routine}
  1494.                 IF myReply.canceled THEN
  1495.                     Exit(DoSubscribe);
  1496.  
  1497.                 {check IF the file has been saved, IF not set pubCFS to NIL}
  1498.                 IF (theDoc^.everSaved = FALSE) THEN
  1499.                     subFSSpec := NIL
  1500.                 ELSE
  1501.                     subFSSpec := @theDoc^.theFSSpec;
  1502.  
  1503.                 {create a publisher section}
  1504.                 err := NewSection(myReply.container,
  1505.                                                     subFSSpec,
  1506.                                                     stSubscriber,
  1507.                                                     mysectionID,
  1508.                                                     sumAutomatic,
  1509.                                                     mySectHdl);
  1510.                                                     
  1511.                 IF err <> noErr THEN
  1512.                     BEGIN
  1513.                         ShowError('NewSection', err);
  1514.                         Exit(DoSubscribe);
  1515.                     END;
  1516.  
  1517.                 theStart := theDoc^.theText^^.selStart;
  1518.                 theEnd   := theDoc^.theText^^.selEnd;
  1519.  
  1520.                 {now add this section to our document list}
  1521.  
  1522.                 CreateSection(mySectHdl, mysectionID, theStart, theEnd, theDoc, NIL);
  1523.  
  1524.                 {read the subscriber in from disk}
  1525.  
  1526.                 ReadAnEdition(mySectHdl);
  1527.  
  1528.             END;                 {DoSubscribe}
  1529.  
  1530. {*-----------------------------------------------------------------------
  1531.         Name:             DoSectionOptions
  1532.         Purpose:        Put up the section option dialogs for a publisher
  1533.                                 or subscriber.    Handle all the various options.
  1534.                                 Note that 'Find Publisher' doesn't work yet.
  1535.  -----------------------------------------------------------------------*}
  1536.  
  1537.         {$S Main}
  1538.  
  1539.         PROCEDURE DoSectionOptions(theDoc: DPtr);
  1540.  
  1541.             VAR
  1542.                 err                     : OSErr;
  1543.                 reply                 : SectionOptionsReply;
  1544.                 theInfo             : EditionInfoRecord;
  1545.                 theAlias            : Handle;
  1546.                 theFormatType : FormatType;
  1547.                 currSection   : SectHandle;
  1548.                 
  1549.             BEGIN
  1550.                 currSection := GetSection(theDoc^.theText^^.selStart,
  1551.                                                                     theDoc^.theText^^.selEnd,
  1552.                                                                     theDoc);
  1553.  
  1554.                 reply.sectionH := currSection^^.fSectHandle;
  1555.                 err := SectionOptionsDialog(reply);
  1556.                 WITH reply DO
  1557.                     BEGIN
  1558.                         IF NOT reply.canceled THEN
  1559.                             BEGIN
  1560.                                 {find out IF there is any action needed}
  1561.                                 IF action = 'read' THEN
  1562.                                 {read the latest version of a subscriber}
  1563.                                     ReadAnEdition(currSection^^.fSectHandle)
  1564.                                 ELSE
  1565.                                     IF action = 'writ' THEN
  1566.                                     {write out the latest version of a publisher to disk}
  1567.                                         WriteAnEdition(currSection^^.fSectHandle)
  1568.                                     ELSE
  1569.                                         IF (action = 'goto') THEN {goto a published section}
  1570.                                             BEGIN
  1571.                                                 err := GetEditionInfo(currSection^^.fSectHandle, theInfo);
  1572.                                                 
  1573.                                                 IF (err <> noErr) THEN
  1574.                                                     ShowError('GetEditionInfo', err);
  1575.                                                     
  1576.                                                 err := GotoPublisherSection(theInfo.container);
  1577.                                                 
  1578.                                                 IF (err <> noErr) THEN
  1579.                                                     ShowError('GotoPublisherSection', err);
  1580.                                             END
  1581.                                         ELSE
  1582.                                             IF (action = 'cncl') THEN {cancel a publisher or subscriber}
  1583.                                                 BEGIN
  1584.                                                     {unRegister the section and delete from our own list}
  1585.                                                     {should have a free PROCEDURE which frees the structures}
  1586.                                                     {associated with a section}
  1587.                                                     err := UnRegisterSection(currSection^^.fSectHandle);
  1588.                                                     DeleteASection(currSection, theDoc);
  1589.  
  1590.                                                     {IF this is the ONLY publisher writing data to this edition}
  1591.                                                     {we should delete the container file as well}
  1592.                                                 END;
  1593.                             END;
  1594.                     END;
  1595.             END;
  1596.  
  1597. END.
  1598.